﻿


#include "VtkWidget.hpp"
#include "../Application/Application.hpp"
#include "../RibbonStyle/FloatBar.hpp"
#include "../RibbonStyle/MenuBar.hpp"
#include "PickManager.hpp"
#include "LegendScaleActor.hpp"
#include <vtkVertex.h>


NAMESPACE_BEGIN(NSVtkWidget)



VtkWidget::VtkWidget(QWidget* parent)
    : QMainWindow(parent) {
    qRegisterMetaType<TopoDS_Shape>("TopoDS_Shape");

    setFocusPolicy(Qt::StrongFocus); 
    // 设置小部件为强聚焦策略
    // 关闭所有日志输出
    vtkLogger::SetStderrVerbosity(vtkLogger::VERBOSITY_OFF);
    Handle(Message_Messenger) aMessenger = Message::DefaultMessenger();
    Message_SequenceOfPrinters printers = aMessenger->Printers();
    for (Standard_Integer i = printers.Lower(); i <= printers.Upper(); ++i) {
        printers.Value(i)->SetTraceLevel(Message_Gravity::Message_Fail);
    }
    // 发送一条错误消息
    //Message::Send("This is an error message", Message_Gravity::Message_Fail);
    /*悬浮菜单*/
    addToolBar(INSTANCE(FloatBar));
    QObject::connect(ACTGP(FloatBar, pick_group), &QActionGroup::triggered, INSTANCE(PickManager) ,&NSPickManager::PickManager::setPickStyleEvent);
    background_id = 0;
    window_id = 0; 
    exchange = nullptr;
    setMouseTracking(true);
    centerMenuSetup();
    //vtkOpenGLRenderWindow::SetGlobalMaximumNumberOfMultiSamples(4);
    QSurfaceFormat::setDefaultFormat(QVTKOpenGLNativeWidget::defaultFormat(true));
    opengl_widget = new QVTKOpenGLNativeWidget(this);
    opengl_widget->setMouseTracking(true);
    setCentralWidget(opengl_widget);
    /*设置渲染窗口*/
    style = SP(NSInteractorStyle::InteractorStyle, )::New();
    render_window = SP(vtkGenericOpenGLRenderWindow, )::New();
    hover_text = SP(vtkCaptionActor2D, )::New();
    style->setHoverTextActor(hover_text);
    // 设置多重采样属性以开启抗锯齿
    // 可以调整采样数，通常 4 或 8 效果较好
    render_window->SetMultiSamples(2);
    render_window->SetLineSmoothing(false);
    opengl_widget->setRenderWindow(render_window);
    /*模型的渲染器*/
    renderer = SP(vtkRenderer, )::New();
    render_window->AddRenderer(renderer);
    /*相机*/
    camera = SP(vtkCamera, )::New();
    renderer->SetActiveCamera(camera);
    camera->UseOffAxisProjectionOff();
    camera->ComputeViewPlaneNormal();
    /*Light*/
    createDefaultLight();
    last_picked_property = SP(vtkProperty, )::New();
    style->SetDefaultRenderer(renderer);
    INSTANCE(PickManager)->setDefaultRenderer(renderer);
    render_window->GetInteractor()->SetInteractorStyle(style);
    SP(vtkActor, ) focus_actor = style->getFocusPointActor();
    renderer->AddActor(focus_actor);
    renderer->AddActor(hover_text);
    //ColorBarWidget
    colorWidgetSetup();
    camOrientWidgetInit();
    orientationWidgetSetup();
    /*显示坐标系的vtk组件 */
    copyrightTextInit();
    /*坐标轴*/
    globalCoordinateInit();
    /*默认提示信息*/
    softwareInfoInit();
    /*渐变的背景*/
// 设置顶部较浅的蓝色背景
    renderer->SetBackground(0.7, 0.8, 0.9);

    // 设置底部较深的蓝色背景
    renderer->SetBackground2(0.2, 0.3, 0.5);
    renderer->SetGradientBackground(true);
    /*添加缩放条*/
    vtkNew<NSLegendScaleActor::LegendScaleActor> scale_actor;
    renderer->AddViewProp(scale_actor);

    /********************测试代码BEGIN********************/
    //NSBCActor::BCActor bc;
    //NSForceActor::ForceActor force;
    //std::vector<std::vector<double>> op = {
    //    {-30,-20,0},
    //    {-30,-15,0},
    //    {-30,-10,0},
    //    {-30,-5,0},
    //    {-30,0,0},
    //    {-30,5,0},
    //    {-30,10,0},
    //    {-30,15,0},
    //    {-30,20,0},
    //};
    //std::vector<std::vector<double>> op1 = {
    //    {30,-20,0,10,0,0 },
    //    {30,-15,0,11,0,0 },
    //    {30,-10,0,12,0,0 },
    //    {30,-5,0,13,0,0 },
    //    {30,0,0,14,0,0 },
    //    {30,5,0,13,0,0 },
    //    {30,10,0,12,0,0 },
    //    {30,15,0,11,0,0 },
    //    {30,20,0,10,0,0 },
    //};
    //bc.setFixedPoints(op);
    //force.setNodePoints(op1);
    //SP(vtkActor, bc_actor) = bc.getActor();
    //SP(vtkActor, force_actor) = force.getActor();
    //renderer->AddActor(bc_actor);
    //renderer->AddActor(force_actor);


    //for (int i = 1; i < 7; i++) {
    //    // 创建第一个滑动条（控制球体半径）
    //    vtkNew<vtkSliderRepresentation2D> slider_rep;
    //    slider_rep->SetMinimumValue(-180);
    //    slider_rep->SetMaximumValue(180);
    //    slider_rep->SetValue(0);
    //    //char buff[100];
    //    //sprintf(buff, "joint-%d", i);
    //    //slider_rep->SetTitleText(buff);
    //    slider_rep->GetPoint1Coordinate()->SetCoordinateSystemToNormalizedDisplay();
    //    slider_rep->GetPoint2Coordinate()->SetCoordinateSystemToNormalizedDisplay();
    //    slider_rep->GetPoint1Coordinate()->SetValue(0.01, 0.3 + i * 0.08);
    //    slider_rep->GetPoint2Coordinate()->SetValue(0.15, 0.3 + i * 0.08);
    //    slider_rep->GetLabelProperty()->SetFontSize(18);
    //    slider_rep->GetLabelProperty()->SetShadow(false);
    //    slider_rep->GetLabelProperty()->SetItalic(false);
    //    SP(vtkSliderWidget, slider) = vtkSliderWidget::New();
    //    slider->SetInteractor(render_window->GetInteractor());
    //    slider->SetRepresentation(slider_rep);
    //    slider->SetAnimationModeToAnimate();
    //    slider->EnabledOn();
    //    vtkNew<RobotSliderCallback> callback1;
    //    callback1->setJointId(i);
    //    slider->AddObserver(vtkCommand::InteractionEvent, callback1);
    //}
   

    /********************测试代码END********************/

    vtkNew<vtkAreaPicker> areaPicker;
    render_window->GetInteractor()->SetPicker(areaPicker);

    //#define FXAA
#ifdef FXAA
    /*其他设置*/
    renderer->SetUseFXAA(true);
#endif // FXAA

#ifdef DEPTHPEELING
    renderer->UseDepthPeelingOn();
    renderer->UseDepthPeelingForVolumesOn();
#endif // DEPTHPEELING
    /*三项在其他电脑上运行会有显示的问题-慎用*/
    renderer->ResetCamera();
    render_window->Render();




}


void VtkWidget::createDefaultLight() {
    default_light = SP(vtkLight, )::New();
    default_light->SetColor(1, 1, 1);
    default_light->SetLightTypeToCameraLight();
    default_light->SetFocalPoint(renderer->GetActiveCamera()->GetFocalPoint());
    renderer->RemoveAllLights();
    renderer->AddLight(default_light);
	renderer->SetLightFollowCamera(true);
    // 增强灯光强度
    default_light->SetIntensity(1.5);
    default_light->SwitchOn();

	render_window->Render();
}


void VtkWidget::lightSwitchEvent(bool checked) {
    default_light->SetSwitch(checked);
    render_window->Render();
}


void VtkWidget::softwareInfoInit(){

    SP(vtkTextMapper, ) _mapper = SP(vtkTextMapper, )::New();
    // 提示信息
    _mapper->SetInput("Copyright © 2025 KONG CHUIJIANG(kcjsdust@163.com).");
    _mapper->GetTextProperty()->SetVerticalJustificationToBottom();
    _mapper->GetTextProperty()->SetFontFamilyToArial();
    _mapper->GetTextProperty()->SetColor(0.8, 0, 0);
    _mapper->GetTextProperty()->SetFontSize(15);
    vtkNew<vtkActor2D> version_info;
    version_info->SetMapper(_mapper);
    version_info->GetPositionCoordinate()->SetCoordinateSystemToNormalizedDisplay();
    version_info->GetPositionCoordinate()->SetValue(0.02, 0.02);
    info_actors.push_back(version_info);
    renderer->AddActor2D(version_info);

}


void VtkWidget::centerMenuSetup(){
	setContextMenuPolicy(Qt::CustomContextMenu);
	connect(this, SIGNAL(customContextMenuRequested(QPoint /*pos*/)), SLOT(popCenterMenu(QPoint /*pos*/)));
	/*MenuBar*/
    QMenuBar* menu_bar = new QMenuBar(this);
    center_menu = new QMenu(this);
    other_action = new QActionGroup(this);
    center_menu->addActions(other_action->actions());

    QAction* action_rerender = new QAction(this);
	QAction* action_window_fit = new QAction(this);
	QAction* action_focalpoint = new QAction(this);

    action_rerender->setText("重新渲染");
	action_window_fit->setText("窗口适应");
	action_focalpoint->setText("设置旋转中心");

    action_rerender->setIcon(QIcon("resources/icons/icon_rerender.png"));
	action_window_fit->setIcon(QIcon("resources/icons/icon_renderwindow_fit.png"));
	action_focalpoint->setIcon(QIcon("resources/icons/icon_set_focalpoint.png"));

    center_menu->addAction(action_rerender);
	center_menu->addAction(action_window_fit);
	center_menu->addAction(action_focalpoint);

    connect(action_rerender, &QAction::triggered, this, &VtkWidget::renderUpdateEvent);
	connect(action_window_fit, &QAction::triggered, this, &VtkWidget::renderWindowFitAll);
	connect(action_focalpoint, &QAction::triggered, this, &VtkWidget::setRenderWindowFocalpoint);

	menu_bar->addMenu(center_menu);
	setMenuBar(menu_bar);
}



void VtkWidget::setRenderWindowFocalpoint() {
	QPoint point = QCursor::pos();
	vtkNew<vtkPointPicker> point_picker;
	//注册拾取点函数
	point_picker->Pick(point.x(), point.y(), 0, renderer);
	//打印拾取点空间位置
	double picked[3];
	point_picker->GetPickPosition(picked);
	// 获取相机并设置旋转中心
	SP(vtkCamera, camera) = renderer->GetActiveCamera();
	camera->SetFocalPoint(picked);
	//更新旋转点
	style->updateFocusPoint(picked);

}


void VtkWidget::renderWindowFitAll() {
	style->updateFocusPoint(0, 0, 0);
	renderer->ResetCamera();
	render_window->Render();

}


void VtkWidget::redoPickedHighlightEvent() {
    if (last_picked && last_picked_property) {
        last_picked->GetProperty()->DeepCopy(last_picked_property);
        last_picked = nullptr;
		render_window->Render();
        update();
    }
}


void VtkWidget::addPointToViewport(double* pos) {
    if (picked_sigle_point != nullptr) {
        renderer->RemoveActor(picked_sigle_point);
    }
    // 创建一个点云
    vtkNew<vtkPoints> points;
    points->InsertNextPoint(pos);  // 插入一个点
    // 将点添加到PolyData中
    vtkNew<vtkPolyData> polyData;
    polyData->SetPoints(points);
    // 设置点的外观
    vtkNew<vtkVertexGlyphFilter> vertexGlyphFilter;
    vertexGlyphFilter->SetInputData(polyData);
    vertexGlyphFilter->Update();
    // 设置映射器
    vtkNew<vtkPolyDataMapper> mapper;
    mapper->SetInputConnection(vertexGlyphFilter->GetOutputPort());
    // 设置Actor
    vtkNew<vtkActor> actor;
    actor->SetMapper(mapper);
    actor->GetProperty()->SetPointSize(12); 
    actor->GetProperty()->SetColor(0.95, 0, 0);
    picked_sigle_point = actor;

    renderer->AddActor(picked_sigle_point);

}



void VtkWidget::paintEvent(QPaintEvent* event) {



    QMainWindow::paintEvent(event);

}



void VtkWidget::mouseMoveEvent(QMouseEvent* event) {
    emit renderPosMovingSignal(event->pos());

    QMainWindow::mouseMoveEvent(event);
}



void VtkWidget::mouseReleaseEvent(QMouseEvent* event) {
    pick_area[2] = event->pos().x();
    pick_area[3]  = abs(height() - event->pos().y());
    INSTANCE(PickManager)->pickAreaObject(pick_area);


    QMainWindow::mouseReleaseEvent(event);
}



void VtkWidget::mousePressEvent(QMouseEvent* event) {
    int pos[2];
    pick_area[0] = pos[0] = event->pos().x();
    pick_area[1] = pos[1] = abs(height() - event->pos().y());
    if (event->button() == Qt::LeftButton) {
        INSTANCE(PickManager)->pickObject(pos);
        //点拾取
        if (pickstyle == PickPoint) {
            vtkNew<vtkPointPicker> point_picker;
            //注册拾取点函数
            point_picker->Pick(pos[0], pos[1], 0, renderer);
            //打印拾取点空间位置
            double picked[3];
            point_picker->GetPickPosition(picked);
            int id = point_picker->GetPointId();
            //对拾取点进行标记
            if (pickto_where == Arrow && id != -1) {
                emit pickedPointForArrowSignal(picked); 
                addPointToViewport(picked);
                setPickStyle(PickNone);
                setPickToWhere(None);
            }

        }
        //Cell拾取-面拾取
        else if (pickstyle == PickCell) {
            vtkNew<vtkCellPicker> cell_picker;
            cell_picker->SetTolerance(0.005);
            cell_picker->Pick(pos[0], pos[1], 0, renderer);
            vtkActor* actor = cell_picker->GetActor();
            vtkIdType cell_id = cell_picker->GetCellId();
            if (cell_id != -1) {
                //printf("get cell datas Cell id: %d .\n", cell_id);
                actor->GetProperty()->SetColor(HIGHLIGHT_R, HIGHLIGHT_G, HIGHLIGHT_B);
            }
        }
        //3D实体拾取
        else if (pickstyle == PickProp) {
            vtkNew<vtkPropPicker> prop_picker;
            prop_picker->Pick(pos[0], pos[1], 0, renderer);
            SP(vtkAssembly, part_assemly) = prop_picker->GetAssembly();
            if (part_assemly != nullptr) {
                SP(vtkActor, actor) = vtkActor::SafeDownCast(part_assemly->GetParts()->GetItemAsObject(0));
                QString model_name = QString(prop_picker->GetAssembly()->GetObjectName().c_str());
                int model_id = regularModelId(model_name);
                if (model_id < 0) return;
                //恢复上一次的颜色
                redoPickedHighlightEvent();
                //记录高亮本次选取的颜色
                last_picked = actor;
                last_picked_property->DeepCopy(actor->GetProperty());
                //高亮
                actor->GetProperty()->SetColor(HIGHLIGHT_R, HIGHLIGHT_G, HIGHLIGHT_B);
                // 遍历map来查找
				if (pickto_where == Mesh) {
                    TopoDS_Shape shape = exchange->getModel(model_id)->getTShape();
                    //发送信号
                    emit pickedActorForMeshSignal(model_id, shape);
                    setPickStyle(PickNone);
                    setPickToWhere(None);
                }
				else if (pickto_where == Cutter) {
					pickedActorForCutterEvent(actor);
					setPickStyle(PickNone);
					setPickToWhere(None);
				}
            }
        }
        render_window->Render();
        //update();
        
    }


    QMainWindow::mousePressEvent(event);
}



void VtkWidget::addArrowCaptionEvent(NSCaptionData::CaptionData data){

    vtkNew<vtkCaptionWidget> caption;
    vtkNew<vtkCaptionRepresentation> caption_rep;
    SP(vtkCaptionActor2D, caption_actor) = caption_rep->GetCaptionActor2D();
    SP(vtkTextProperty, text_property) = caption_actor->GetCaptionTextProperty();

    caption_actor->SetBorder(data.boundary);
    caption_actor->SetCaption(data.caption.toStdString().c_str());
    caption_actor->SetLeader(data.leader);
    caption_actor->SetPadding(2);
    caption_actor->GetTextActor()->SetTextScaleModeToProp();
    text_property->SetColor(data.font_color.red() / 255.0, data.font_color.green() / 255.0, data.font_color.blue() / 255.0);
    text_property->SetFontFamilyAsString(data.font_str == "Simsun" ? "File" : data.font_str.toStdString().c_str());
    text_property->SetFontFile(QString(QApplication::applicationDirPath() + "/fonts/simsun.ttc").toStdString().c_str());
    text_property->SetJustification(data.adjust);
    text_property->SetVerticalJustificationToCentered();
    text_property->SetBold(data.font_bold);
    text_property->SetItalic(data.font_italic);
    text_property->SetShadow(data.font_shadow);
    text_property->SetFrame(data.frame);
    // 设置背景颜色
    //text_property->SetBackgroundColor(data.background_color.red() / 255.0, data.background_color.green() / 255.0, data.background_color.blue() / 255.0);
    //text_property->SetBackgroundOpacity(1.0);

    double pos[] = { data.point_x, data.point_y, data.point_z };
    caption_rep->SetAnchorPosition(pos);
    caption->SetRepresentation(caption_rep);
    caption->SetInteractor(render_window->GetInteractor());
    caption->SetDefaultRenderer(renderer);
    caption->EnabledOn();
    caption_map[data.id] = caption;

    renderer->Render();
    update();

}


void VtkWidget::pickOneActorForMeshEvent(bool checked){
    //设置选取模式 Mesh
    setPickStyle(checked ? PickStyle::PickProp : PickStyle::PickNone);
    setPickToWhere(checked ? PickToWhere::Mesh : PickToWhere::None);
}



void VtkWidget::pickOneActorForCutterEvent(bool checked) {
    //设置选取模式 Mesh
    setPickStyle(checked ? PickStyle::PickProp : PickStyle::PickNone);
    setPickToWhere(checked ? PickToWhere::Cutter : PickToWhere::None);
}



void VtkWidget::closeEvent(QCloseEvent* event){
    int id = getWindowID();
    QMessageBox::StandardButton reply;
    QString tip_text = "窗口中的模型将被删除，确定要删除该窗口?";
    if (id == 0) {
        tip_text = "默认渲染窗口不可删除！";
    }
    reply = QMessageBox::information(this, tr("移除提示"),
        tip_text,
        QMessageBox::Ok | QMessageBox::Cancel);
    
    if (reply == QMessageBox::Cancel || id == 0) {
        event->ignore();
        return;
    }
    emit removeActorsInWidgetSignal(renderingid_inthis);
    emit closeCenterWidgetSignal(id);

    event->accept();

    QMainWindow::closeEvent(event);
}



void VtkWidget::copyrightTextInit(){

    vtkNew<vtkTextMapper> mapper;
    // 提示信息
    mapper->SetInput("MicroWorks 2025");
    mapper->GetTextProperty()->SetVerticalJustificationToTop();
    mapper->GetTextProperty()->SetFontFamilyToArial();
    mapper->GetTextProperty()->SetColor(0.8, 0.8, 0.8);
    mapper->GetTextProperty()->SetFontSize(36);
    mapper->GetTextProperty()->SetBold(true);
    vtkNew<vtkActor2D> info;
    info->SetMapper(mapper);
    info->GetPositionCoordinate()->SetCoordinateSystemToNormalizedDisplay();
    info->GetPositionCoordinate()->SetValue(0.02, 0.98);
    info_actors.push_back(info);
    renderer->AddActor2D(info);
	
}



void VtkWidget::camOrientWidgetInit() {
	camera_widget = SP(vtkCameraOrientationWidget, )::New();
	camera_widget->SetParentRenderer(renderer);
    camera_widget->SetInteractor(render_window->GetInteractor());
    camera_widget->SetAnimate(true);
    camera_widget->SetAnimatorTotalFrames(20);

	camera_widget->EnabledOn();



}


void VtkWidget::partVisibilityEvent(int part_id, bool checked){
    //exchange->getModel(part_id)->getPartFeature()->SetVisibility(checked);
    if (hightlight_meta_actor != nullptr) {
        renderer->RemoveActor(hightlight_meta_actor);
        hightlight_meta_actor = nullptr;
    }
    if (hightlight_part_actor != nullptr) {
        NSModelBase::ModelBase* database = getExchange()->getModel(part_id);
        if (database->isMeshed()) {
            hightlight_part_actor->GetProperty()->SetColor(MESH_R, MESH_G, MESH_B);
        }
        else {
            hightlight_part_actor->GetProperty()->SetColor(MESH_R, SOLID_G, SOLID_B);
        }
        hightlight_part_actor = nullptr;
    }
    /*隐藏装配体的同时隐藏装配体的各种特征*/
    NSModelBase::ModelBase* database = exchange->getModel(part_id);
    database->getAssmFeature()->SetVisibility(checked);
    if (database->hasLaser()) {
        SP(vtkActor2D, label) = database->getLabelActor2D();
        //renderer->RemoveActor2D(label);
        label->SetVisibility(checked);
    }
    render_window->Render();
}




void VtkWidget::renderUpdateEvent(){
    renderer->Render();
    render_window->Render();
}



void VtkWidget::removeModelByIdEvent(int id) {
    cleanTempBoundary();
    //先删除渲染窗口中的Actor
    NSModelBase::ModelBase* database = exchange->getModel(id);
    SP(vtkAssembly, part) = database->getAssemlyPart();
    /*向渲染窗口中添加Actor*/
    renderer->RemoveActor(part);
    /*删除装配体的特征*/
    if (database->hasLaser()) {
        SP(vtkActor2D, label) = database->getLabelActor2D();
        renderer->RemoveActor2D(label);
    }
    //冲ID列表中删除
    removeRenderingIDinThis(id);
    //在删除数据库中的模型
    exchange->removeModelById(id);
    render_window->Render();

}


// 计算给定点的法向量
void VtkWidget::getNormalByPoint(SP(vtkPolyData, poly_data), double pos[3], double normal[3]) {
    // 创建法向量计算器
    vtkNew<vtkPolyDataNormals> normals;
    normals->SetInputData(poly_data);
    normals->ComputePointNormalsOn();  // 开启点法向量计算
    normals->ComputeCellNormalsOff();  // 关闭单元法向量计算
    normals->Update();
    // 创建一个单元定位器
    vtkNew<vtkCellLocator> cell_locator;
    cell_locator->SetDataSet(normals->GetOutput());
    cell_locator->BuildLocator();
    // 创建一个通用单元对象
    vtkNew<vtkGenericCell> generic_cell;
    // 查找包含指定点的单元
    vtkIdType cellId = -1;
    int subId = -1;
    double dist = 0.0;
    double closest_point[3];
    cell_locator->FindClosestPoint(pos, pos, generic_cell, cellId, subId, dist);

    if (cellId != -1) {
        // 获取指定点的法向量
        SP(vtkDataArray, normal_data) = normals->GetOutput()->GetPointData()->GetNormals();
        if (normal_data) {
            normal_data->GetTuple(generic_cell->GetPointId(0), normal);
            //std::cout << "n_x: " << normal[0] << " n_y: " << normal[1] << " n_z: " << normal[2] << std::endl;
        }
    }
    else {
        // 如果没有找到对应的单元，normal数组保持未初始化状态
        // 可以选择在这里处理错误或设置默认值
        //qDebug() << "No cell found for the given point.";
    }
}



void VtkWidget::addLaserPoint(NSModelBase::ModelBase* database) {
    SP(vtkRenderer, renderer) = getRenderer();
    SP(vtkAssembly, part) = database->getAssemlyPart();
    if (database->hasLaser()) {
        SP(vtkPolyData, poly) = database->getPolyData();
        vtkNew<vtkAppendPolyData> append_poly;
        int pointIndex = 1;
        // Start numbering from 1
        // Create a vertex for each laser point and add axes
        vtkNew<vtkPoints> points;
        vtkNew<vtkCellArray> vertices;
        vtkNew<vtkStringArray> labels;
        labels->SetName("Labels");
        // Create an axes source to be used for all points
        vtkNew<vtkAxes> axes;
        // 获取包围盒
        double bounds[6];
        poly->GetBounds(bounds);
        // 计算每个维度的尺寸
        double xSize = bounds[1] - bounds[0];
        double ySize = bounds[3] - bounds[2];
        double zSize = bounds[5] - bounds[4];
        double aver = (xSize + ySize + zSize) / (15.0);
        axes->SetScaleFactor(aver);
        vtkNew<vtkPolyData> axesPolyData;
        axes->Update();
        // Ensure the axes data is up-to-date
        axesPolyData->ShallowCopy(axes->GetOutput());
        for (auto& item : database->getLaserPoints()) {
            NSLaserPoint::LaserPoint laser_point = item.second;
            double pos[3];
            laser_point.XYZ(pos);
            // Add a single vertex at the position of each laser point
            vtkIdType pid = points->InsertNextPoint(pos);
            vertices->InsertNextCell(1);
            vertices->InsertCellPoint(pid);
            labels->InsertNextValue(std::to_string(pointIndex++));
            // Create a transform for the axes
            vtkNew<vtkTransform> transform;
            transform->Translate(pos);
            if (ACTION(MenuBar, normal_laser)->isChecked()) {
                double normal[3], z_axis[3] = { 0, 0, 1 }, rotation_axis[3];
                getNormalByPoint(poly, pos, normal);
                vtkMath::Cross(z_axis, normal, rotation_axis);
                double angle = vtkMath::DegreesFromRadians(vtkMath::AngleBetweenVectors(z_axis, normal));
                transform->RotateWXYZ(angle, rotation_axis);
            }
            // Apply the transform to the axes
            vtkNew<vtkTransformPolyDataFilter> axesTransformFilter;
            axesTransformFilter->SetInputData(axesPolyData);
            axesTransformFilter->SetTransform(transform);
            axesTransformFilter->Update();
            // Append the transformed axes to the append filter
            append_poly->AddInputData(axesTransformFilter->GetOutput());
        }
        // Create PolyData with the points and vertices
        vtkNew<vtkPolyData> point_poly_data;
        point_poly_data->SetPoints(points);
        point_poly_data->SetVerts(vertices);
        point_poly_data->GetPointData()->AddArray(labels);
        // Use vtkVertexGlyphFilter to ensure the points are not scaled
        vtkNew<vtkVertexGlyphFilter> vertexFilter;
        vertexFilter->SetInputData(point_poly_data);
        vertexFilter->Update();
        // Append the vertices to the existing polydata
        append_poly->AddInputData(vertexFilter->GetOutput());
        // After processing all points, create mapper and actor for the appended polydata
        vtkNew<vtkPolyDataMapper> pulser_mapper;
        pulser_mapper->SetInputConnection(append_poly->GetOutputPort());
        vtkNew<vtkActor> pulser_actor;
        pulser_actor->SetMapper(pulser_mapper);
        pulser_actor->GetProperty()->SetColor(1.0, 0.0, 0.0); // Red color for the points
        // Set the point size
        pulser_actor->GetProperty()->SetPointSize(8); // Set the desired point size here
        // Add the final actor to the scene
        pulser_actor->SetPickable(false);
        part->AddPart(pulser_actor);
        // If you want to display text labels next to the points, you can use vtkLabelPlacementMapper
        // and vtkLabeledDataMapper. Here is an example on how to do it:
        // Create text labels next to the points
        // Configure label properties
        //vtkNew<vtkTextProperty> labelTextProperty;
        //labelTextProperty->SetColor(0.0, 0.0, 0.0); // Black color for the labels
        //labelTextProperty->SetFontSize(18); // Adjust font size as needed
        //labelTextProperty->BoldOff(); // Make the text bold
        //// Add the labels array to the point data, not field data.
        //point_poly_data->GetPointData()->AddArray(labels.GetPointer());
        //// Create Labeled Data Mapper
        //vtkNew<vtkLabeledDataMapper> labelMapper;
        //labelMapper->SetInputData(point_poly_data);
        //labelMapper->SetLabelTextProperty(labelTextProperty);
        //// If you want to label based on a specific array in point data:
        //labelMapper->SetLabelModeToLabelScalars(); // This will look for scalars in point data
        //// If your labels are stored in an array named "Labels":
        //// labelMapper->SetLabelFormat("%g"); // For numeric labels
        //// Or if they are string labels:
        //labelMapper->SetLabelFormat("LP-%s");
        //labelMapper->SetLabelModeToLabelFieldData();
        //// Create Actor2D for the labels
        //vtkNew<vtkActor2D> labelActor;
        //labelActor->SetMapper(labelMapper);
        //// Add the label actor to the renderer or scene
        //database->setLabelActor2D(labelActor);
        //renderer->AddActor2D(labelActor);

    }

    renderer->AddActor(part);

}



void VtkWidget::renderRobotData(NSRobotBase::RobotBase* robotbase) {
    /*Assembly Abandoned*/
    //addRenderingIDinThis(robotbase->getRobotId());
    /*更改坐标系的大小*/
    double min_size = 1.0;
    for (auto& actor : robotbase->getJoints()) {
        double b_size = getMinBoundary(vtkActor::SafeDownCast(actor->GetParts()->GetItemAsObject(0)));
        min_size = b_size > min_size ? b_size : min_size;
    }
    default_axes->SetScale(min_size*2);
    /*Rendering*/
    SP(vtkRenderer, renderer) = getRenderer();
    SP(vtkAssembly, assembly) = robotbase->getAssembly();
    renderer->AddActor(assembly);

    //INSTANCE(RobotExchange)->getRobot(0)->getJoints(0)->RotateZ(-90);
    //INSTANCE(RobotExchange)->getRobot(0)->getJoints(1)->RotateZ(-90);


    renderer->ResetCamera();
    render_window->Render();

}



/*所有通过线程读取的模型都会在这里添加进renderer*/
void VtkWidget::renderModelData(NSModelBase::ModelBase* database){
    /*Assembly Abandoned*/
    /*在添加Part之前先改变渲染窗口，防止添加到其他窗口*/
    addLaserPoint(database);
    addRenderingIDinThis(database->getPartID());
    /*添加Node Label*/
    //SP(vtkActor2D, ) node_label = database->getNodeLabelActor2D();
    //SP(vtkActor2D, ) elem_label = database->getElemLabelActor2D();
    //renderer->AddActor2D(node_label);
    //renderer->AddActor2D(elem_label);
	/*更改坐标系的大小*/
	double min_size = 1.0;
    
	for (auto&actor : exchange->getModels()) {
		double b_size = getMinBoundary(actor.second->getPartFeature());
		min_size = b_size > min_size ? b_size : min_size;
	}
    default_axes->SetScale(min_size);
    /*Rendering*/
    SP(vtkRenderer, renderer) = getRenderer();

    renderer->ResetCamera();
	render_window->Render();


}



int VtkWidget::regularModelId(QString _bref) {
    QRegularExpression re("Model-([0-9]+)\\(.*?\\)");
    QRegularExpressionMatchIterator i = re.globalMatch(_bref);
    while (i.hasNext()) {
        QRegularExpressionMatch match = i.next();
        if (match.hasMatch()) {
            QString number = match.captured(1);
            return number.toInt() - 1;
        }
    }
    return -1;
}



// 计算 Actor 的包围盒并返回最小尺寸
double VtkWidget::getMinBoundary(SP(vtkActor, _actor)) {
	// 获取包围盒
	double bounds[6];
    _actor->GetBounds(bounds);
	// 计算每个维度的尺寸
	double xSize = bounds[1] - bounds[0];
	double ySize = bounds[3] - bounds[2];
	double zSize = bounds[5] - bounds[4];
	// 找出最小的尺寸
    double aver = (xSize + ySize + zSize) / (200.0);

	return aver;
}


void VtkWidget::redoHighlightMetaEvent(int part_id, int meta_id){
    if (hightlight_meta_actor != nullptr) {
        renderer->RemoveActor(hightlight_meta_actor);
        hightlight_meta_actor = nullptr;
   }
	render_window->Render();


}



void VtkWidget::doHighlightMetaEvent(int part_id, int meta_id){
 //   if (hasData()) {
 //       NSModelBase::ModelBase* database = getExchange()->getModel(part_id);
 //       SP(vtkActor, meta_actor) = database->getMetaActor(meta_id);
 //       meta_actor->GetProperty()->SetColor(HIGHLIGHT_META_R, HIGHLIGHT_META_G, HIGHLIGHT_META_B);
 //       renderer->AddActor(meta_actor);
 //       hightlight_meta_actor = meta_actor;

 //   }
	//render_window->Render();

}



void VtkWidget::redoHighlightPartEvent(int part_id){

    if (hightlight_part_actor != nullptr) {
        NSModelBase::ModelBase* database = getExchange()->getModel(part_id);
        if (database->isMeshed()) {
            hightlight_part_actor->GetProperty()->SetColor(MESH_R, MESH_G, MESH_B);
        }
        else {
            hightlight_part_actor->GetProperty()->SetColor(MESH_R, SOLID_G, SOLID_B);
        }
        hightlight_part_actor = nullptr;
    }
	render_window->Render();

}


void VtkWidget::redoAllHighlightEvent() {
    if (hightlight_meta_actor != nullptr) {
        renderer->RemoveActor(hightlight_meta_actor);
        hightlight_meta_actor = nullptr;
    }
    if (hightlight_part_actor != nullptr) {
        for (auto& item : exchange->getModels()) {
            NSModelBase::ModelBase* database = item.second;
            if (database->isMeshed()) {
                hightlight_part_actor->GetProperty()->SetColor(MESH_R, MESH_G, MESH_B);
            }
            else {
                hightlight_part_actor->GetProperty()->SetColor(SOLID_R, SOLID_G, SOLID_B);
            }
        }        
        hightlight_part_actor = nullptr;
    }
}



void VtkWidget::doHighlightPartEvent(int part_id){
    if (hasData()) {
        SP(vtkActor, part_actor) = exchange->getModel(part_id)->getPartFeature();
        part_actor->GetProperty()->SetColor(HIGHLIGHT_R, HIGHLIGHT_G, HIGHLIGHT_B);
        hightlight_part_actor = part_actor;
    }
	render_window->Render();

}




void VtkWidget::setCameraOrientation(CamOrientation _ori){
    SP(vtkCamera, camera) = renderer->GetActiveCamera();
    if (camera == nullptr)return;
    camera->SetFocalPoint(0, 0, 0);
    switch (_ori){
    case Up:
        camera->SetPosition(0, 0, 1);
        camera->SetViewUp(0, 1, 0);
        break;
    case Down:
        camera->SetPosition(0, 0, -1);
        camera->SetViewUp(0, 1, 0);
        break;
    case Left:
        camera->SetPosition(0, -1, 0);
        camera->SetViewUp(0, 0, 1);
        
        break;
    case Right:
        camera->SetPosition(0, 1, 0);
        camera->SetViewUp(0, 0, 1);
        break;
    case Front:
        camera->SetPosition(1, 0, 0);
        camera->SetViewUp(0, 0, 1);
        break;
    case Back:
        camera->SetPosition(-1, 0, 0);
        camera->SetViewUp(0, 0, 1);
        break;
    case Axon:
        camera->SetPosition(1, 1, 1);
        camera->SetViewUp(0, 0, 1);
            break;
    default:
        break;
    }
    renderer->ResetCamera();
    render_window->Render();

}


void VtkWidget::setSolidViewStyle(bool checked) {
    for (const auto& pair : exchange->getModels()) {
        pair.second->getPartFeature()->SetVisibility(checked);
    }
    render_window->Render();
}


void VtkWidget::setEdgeViewStyle(bool checked) {
    for (const auto& pair : exchange->getModels()) {
        pair.second->getBoudaryFeature()->SetVisibility(checked);
    }
    render_window->Render();
}


void VtkWidget::setPointsViewStyle(bool checked) {
    for (const auto& pair : exchange->getModels()) {
        pair.second->getPointFeature()->SetVisibility(checked);
    }
    render_window->Render();
}


void VtkWidget::setFrameViewStyle(bool checked) {
    for (const auto& pair : exchange->getModels()) {
        pair.second->getMeshFeature()->SetVisibility(checked);
    }
    render_window->Render();
}



void VtkWidget::showBoundaryBox(bool checked){
    if (!checked) {
        cleanTempBoundary();
        return;
    }
    //temp_boundary
    vtkNew<vtkAssembly> boundary;
    // 获取模型的边界
    double bounds[6];
    for (int id : getRenderingIDinThis()) {
        //first : id; second: vtkActor
        SP(vtkActor, actor) = exchange->getModel(id)->getPartFeature();
        actor->GetBounds(bounds);
        // 创建边界框过滤器
        SP(vtkOutlineFilter, outlineFilter) = SP(vtkOutlineFilter, )::New();
        outlineFilter->SetInputData(actor->GetMapper()->GetInput());
        outlineFilter->Update();
        // 创建边界框的映射器和演员
        SP(vtkPolyDataMapper, outlineMapper) = SP(vtkPolyDataMapper, )::New();
        outlineMapper->SetInputConnection(outlineFilter->GetOutputPort());
        SP(vtkActor, outlineActor) = SP(vtkActor, )::New();
        outlineActor->SetMapper(outlineMapper);
        outlineActor->GetProperty()->SetColor(BOUNDARY_R, BOUNDARY_G, BOUNDARY_B);
        // 计算边界框的边的中点位置
        double center_x[3], center_y[3], center_z[3];
        center_x[0] = (bounds[0] + bounds[1]) / 2.0;
        center_x[1] = bounds[3]; 
        center_x[2] = bounds[5];
        center_y[0] = bounds[0];
        center_y[1] = (bounds[2] + bounds[3]) / 2.0;
        center_y[2] = bounds[5];
        center_z[0] = bounds[0];
        center_z[1] = bounds[3];
        center_z[2] = (bounds[4] + bounds[5]) / 2.2;

        vtkNew<vtkBillboardTextActor3D> x_size_actor;
        vtkNew<vtkBillboardTextActor3D> y_size_actor;
        vtkNew<vtkBillboardTextActor3D> z_size_actor;
        // 设置文本属性
        x_size_actor->SetPosition(center_x);
        y_size_actor->SetPosition(center_y);
        z_size_actor->SetPosition(center_z);
        x_size_actor->GetTextProperty()->SetColor(BOUNDARY_R, BOUNDARY_G, BOUNDARY_B);
        x_size_actor->GetTextProperty()->SetFontFamilyToArial();
        x_size_actor->GetTextProperty()->SetFontSize(18);
        y_size_actor->GetTextProperty()->SetColor(BOUNDARY_R, BOUNDARY_G, BOUNDARY_B);
        y_size_actor->GetTextProperty()->SetFontFamilyToArial();
        y_size_actor->GetTextProperty()->SetFontSize(18);
        z_size_actor->GetTextProperty()->SetColor(BOUNDARY_R, BOUNDARY_G, BOUNDARY_B);
        z_size_actor->GetTextProperty()->SetFontFamilyToArial();
        z_size_actor->GetTextProperty()->SetFontSize(18);
        x_size_actor->SetInput((QString::number(bounds[1] - bounds[0]) + " mm").toStdString().c_str());
        y_size_actor->SetInput((QString::number(bounds[3] - bounds[2]) + " mm").toStdString().c_str());
        z_size_actor->SetInput((QString::number(bounds[5] - bounds[4]) + " mm").toStdString().c_str());
        renderer->AddActor(x_size_actor);
        renderer->AddActor(y_size_actor);
        renderer->AddActor(z_size_actor);
        boundary->AddPart(outlineActor);
        renderer->AddActor(boundary);

        temp_boundary_text.push_back(x_size_actor);
        temp_boundary_text.push_back(y_size_actor);
        temp_boundary_text.push_back(z_size_actor);
        temp_boundary_asm.push_back(boundary);

    }
    render_window->Render();

}



void VtkWidget::cleanTempBoundary(){
    for (auto& item : temp_boundary_asm) {
        renderer->RemoveActor(item);
    }
    for (auto& item : temp_boundary_text) {
        renderer->RemoveActor(item);
    }
    temp_boundary_asm.clear();
    temp_boundary_text.clear();
    render_window->Render();

}


void VtkWidget::removeCapActor() {
    for (auto& pair : caption_map) {
        pair.second->Off();
        pair.second = nullptr;
    }
    //删除map
    caption_map.clear();
    render_window->Render();
    update();
}


void VtkWidget::removeCapActorById(int id) {
    SP(vtkCaptionWidget, cap_widget)= caption_map[id];
    cap_widget->Off();
    cap_widget = nullptr;
    caption_map.erase(id);
    render_window->Render();
    update();
}



void VtkWidget::viewCapture() {
    // 获取当前 VtkWidget 的截图
    QPixmap screenshot = this->grab();
    QString default_name = QDateTime::currentDateTime().toString("yyyyMMdd_HHmmss") + ".png";
    QString filename = QFileDialog::getSaveFileName(this, tr("Save Screenshot"), default_name, tr("PNG Images (*.png)"));
    if (!filename.isEmpty()) {
        if (screenshot.save(filename, "PNG")) {
            INSTANCE(Logger)->log(QString("%1保存成功.").arg(filename));
        }
        else {
            INSTANCE(Logger)->log(QString("%1保存失败.").arg(filename), NSLogger::LOGERROR);
        }
    }

}



void VtkWidget::orientationWidgetSetup() {
    orientation_widget = SP(vtkOrientationMarkerWidget, )::New();
    vtkNew<vtkAxesActor> axes_actor;
    axes_actor->SetPosition(0, 0, 0);
    axes_actor->SetShaftType(0);
    axes_actor->SetCylinderRadius(0.04);
    axes_actor->SetConeRadius(.0);

    vtkNew<vtkSphereSource> sphere;
    sphere->SetCenter(0.0, 0.0, 0.0);
    sphere->SetRadius(0.1);
    sphere->SetThetaResolution(40);
    sphere->SetPhiResolution(40);
    sphere->Update();
    vtkNew<vtkPolyDataMapper> sphere_mapper;
    sphere_mapper->SetInputConnection(sphere->GetOutputPort());
    vtkNew<vtkActor> actor;
    actor->SetMapper(sphere_mapper);

    vtkNew<vtkAssembly> axes_assemblyr;
    axes_assemblyr->AddPart(axes_actor);
    axes_assemblyr->AddPart(actor);

    orientation_widget->SetOrientationMarker(axes_assemblyr);
    orientation_widget->SetInteractor(opengl_widget->interactor());
    orientation_widget->SetEnabled(true);
    orientation_widget->InteractiveOff();
    //orientation_widget->SetViewport(0.94, 0.02, 1.0, 0.2);

}



void VtkWidget::globalCoordinateInit() {
    int length = 15;
	//创建一个vtkAxesActor
	vtkNew<vtkBillboardTextActor3D> origin;
	origin->SetInput("WCS");
	origin->SetPosition(0., 0., 0.);
	renderer->AddActor(origin);
    // 创建点
    vtkNew<vtkPoints> points;
    points->InsertNextPoint(0.0, 0.0, 0.0);  // 原点
    points->InsertNextPoint(length, 0.0, 0.0);  // X 轴终点
    points->InsertNextPoint(0.0, length, 0.0);  // Y 轴终点
    points->InsertNextPoint(0.0, 0.0, length);  // Z 轴终点
    // 创建线段
    vtkNew<vtkCellArray> lines;
    vtkNew<vtkLine> lineX;
    lineX->GetPointIds()->SetId(0, 0);
    lineX->GetPointIds()->SetId(1, 1);
    lines->InsertNextCell(lineX);
    vtkNew<vtkLine> lineY;
    lineY->GetPointIds()->SetId(0, 0);
    lineY->GetPointIds()->SetId(1, 2);
    lines->InsertNextCell(lineY);
    vtkNew<vtkLine> lineZ;
    lineZ->GetPointIds()->SetId(0, 0);
    lineZ->GetPointIds()->SetId(1, 3);
    lines->InsertNextCell(lineZ);
    // 创建多边形数据
    vtkNew<vtkPolyData> polyData;
    polyData->SetPoints(points);
    polyData->SetLines(lines);
    // 创建映射器和演员
    vtkNew<vtkPolyDataMapper> mapper;
    mapper->SetResolveCoincidentTopologyToPolygonOffset();
    mapper->SetRelativeCoincidentTopologyLineOffsetParameters(0, -66000);
    mapper->SetRelativeCoincidentTopologyPolygonOffsetParameters(0, -66000);
    mapper->SetRelativeCoincidentTopologyPointOffsetParameter(-66000);
    mapper->SetInputData(polyData);

    default_axes = vtkActor::New();
    default_axes->SetMapper(mapper);
    default_axes->GetProperty()->SetColor(1.0, 1.0, 0.0);  // 黄色
    default_axes->GetProperty()->SetLineWidth(2);

	style->setAxes(default_axes);


}



void VtkWidget::pickedActorForCutterEvent(SP(vtkActor, actor)) {
	SP(vtkPolyDataMapper, mapper)= vtkPolyDataMapper::SafeDownCast(actor->GetMapper());
	

}



void VtkWidget::addCoordinateEvent(int x, int y, int z, CoordType type) {
    //创建一个vtkAxesActor
    vtkNew<vtkBillboardTextActor3D> origin;
    origin->SetInput("CS-1");
    origin->SetPosition(x, y, z);
    renderer->AddActor(origin);
    vtkNew<vtkAxesActor> coord_actor;
    vtkNew<vtkTransform>  userTrans;
    userTrans->Translate(x, y, z);
    userTrans->Update();
    coord_actor->SetUserTransform(userTrans);
    switch (type){
    case Global:
        /*坐标轴顶置*/
        coord_actor->SetConeRadius(.0);
        coord_actor->SetTotalLength(5, 5, 5);
        coord_actor->SetShaftTypeToCylinder();
        coord_actor->SetCylinderRadius(0.004);
        coord_actor->GetXAxisCaptionActor2D()->GetCaptionTextProperty()->SetFontSize(18);
        coord_actor->GetYAxisCaptionActor2D()->GetCaptionTextProperty()->SetFontSize(18);
        coord_actor->GetZAxisCaptionActor2D()->GetCaptionTextProperty()->SetFontSize(18);
        coord_actor->GetXAxisCaptionActor2D()->GetTextActor()->SetTextScaleModeToNone();
        coord_actor->GetYAxisCaptionActor2D()->GetTextActor()->SetTextScaleModeToNone();
        coord_actor->GetZAxisCaptionActor2D()->GetTextActor()->SetTextScaleModeToNone();
        ///*RGB  223, 232, 20*/
        
        break;
    case Local:

        break;
    default:
        break;
    }
    renderer->AddActor(coord_actor);

}




void VtkWidget::computeNormalEvent(bool checked) {
	static std::vector<SP(vtkActor, )> normals_actor;
	for (auto& actor : normals_actor) {
		renderer->RemoveActor(actor);
	}
	renderer->Render();
	if (!checked) return;
	for (auto& model : exchange->getModels()) {
        SP(vtkActor, actor) = model.second->getPartFeature();
        if (!actor->GetVisibility()) continue;
		// 获取actor的mapper
		SP(vtkPolyDataMapper, mapper) = vtkPolyDataMapper::SafeDownCast(actor->GetMapper());
		vtkNew<vtkPolyDataNormals> normFilter;
		normFilter->SetInputData(mapper->GetInput());
		normFilter->SetComputePointNormals(true);
		normFilter->SetComputeCellNormals(false);
		normFilter->SetAutoOrientNormals(false);
		normFilter->SetSplitting(0);
		normFilter->Update();
		vtkNew<vtkMaskPoints> mask;
		mask->SetInputData(normFilter->GetOutput());
		mask->Update();
		vtkNew<vtkArrowSource> arrow;
		arrow->Update(); //一定要更新 否则数据没有添加进来，程序会报错

		vtkNew<vtkGlyph3D> glyph;
		glyph->SetInputData(mask->GetOutput());
		glyph->SetSourceData(arrow->GetOutput());//每一点用箭头代替
		glyph->SetVectorModeToUseNormal();//设置向量显示模式和法向量一致
		glyph->SetScaleFactor(1); //设置伸缩比例
		glyph->Update();

		vtkNew<vtkPolyDataMapper> glyphMapper;
		glyphMapper->SetInputData(glyph->GetOutput());

		vtkNew<vtkActor> glyphActor;
		glyphActor->SetMapper(glyphMapper);
		glyphActor->GetProperty()->SetColor(0, 1.0, 0);
		glyphActor->SetPickable(false);

		renderer->AddActor(glyphActor);
		renderer->Render();

		normals_actor.push_back(glyphActor);
	}
}




void VtkWidget::computeCurvatureEvent(bool checked) {
    scalar_bar->SetTitle("Curvature\nMean\n");
    for (auto& model : exchange->getModels()) {
        SP(vtkActor, actor) = model.second->getPartFeature();
        if (!actor->GetVisibility()) continue;
        // 获取actor的mapper
        SP(vtkPolyDataMapper, mapper) = vtkPolyDataMapper::SafeDownCast(actor->GetMapper());
        mapper->SetScalarVisibility(checked);
        if (!checked) continue;

		vtkNew<vtkTriangleFilter>	triangle_filter;
		triangle_filter->SetInputData(mapper->GetInput());
		triangle_filter->SetPassLines(true);
		triangle_filter->Update();
        vtkNew<vtkGeometryFilter> gemo_filter;
        gemo_filter->SetInputData(triangle_filter->GetOutput());
        gemo_filter->Update();
        vtkNew<vtkCurvatures> curvature_filter;
        curvature_filter->SetInputConnection(gemo_filter->GetOutputPort());
        //curvature_filter->SetCurvatureTypeToMinimum();
        //curvature_filter->SetCurvatureTypeToMaximum();
        //curvature_filter->SetCurvatureTypeToGaussian();
        curvature_filter->SetCurvatureTypeToMean();
        curvature_filter->Update();

        double _range[2];
        curvature_filter->GetOutput()->GetScalarRange(_range);
        mapper->SetScalarRange(_range);
        color_lut->SetTableRange(_range);
        mapper->SetLookupTable(color_lut);
        mapper->SetInputConnection(curvature_filter->GetOutputPort());
        //设置颜色映射的数目
        color_lut->SetNumberOfTableValues(14);
        //色调范围从红色到蓝色
        color_lut->SetHueRange(0.0, 0.67);

    }

    scalar_bar->SetVisibility(checked);
    render_window->Render();
}


void VtkWidget::colorWidgetSetup() {
    scalar_bar = SP(NSScalarBarActor::MyScalarBarActor, )::New();
    color_lut = SP(vtkLookupTable, )::New();
    //设置颜色映射的数目
    color_lut->SetNumberOfTableValues(14);
    color_lut->SetHueRange(0.67, 0.0);      //色调范围从红色到蓝色
    //设置颜色映射的范围
    color_lut->SetTableRange(0, 100);
    color_lut->SetAnnotation(0.0, "Min");
    color_lut->SetAnnotation(50, "Half");
    color_lut->SetAnnotation(100, "Max");

    color_lut->Build();

    scalar_bar->SetLookupTable(color_lut);
    scalar_bar->SetTitle("Mises (MPa)\nAverage 75%\n");
    scalar_bar->SetVisibility(false);
    //scalar_bar->SetPosition2(0.95, 0.85);
    renderer->AddActor2D(scalar_bar);

}



VtkWidget::~VtkWidget(){
    if (opengl_widget != nullptr) delete opengl_widget;

}



void VtkWidget::changeRenderBackgroundEvent() {
    background_id = (background_id + 1) % 3;
    if (background_id == 0) {
        /*渐变的背景*/
        renderer->SetBackground(0.8, 0.8, 1.0);
        renderer->SetBackground2(0.2, 0.4, 0.6);
        renderer->SetGradientBackground(true);
    }
    else if (background_id == 1) {
        renderer->SetBackground(1, 1, 1);
        renderer->SetGradientBackground(false);
    }
    else {
        renderer->SetBackground(0, 0, 0);
        renderer->SetGradientBackground(false);
    }
    render_window->Render();

}






void VtkWidget::tidyViewEvent(bool checked){
    if (checked) {
        for (vtkActor2D* actor : getInfoActors2D()) {
            renderer->RemoveActor2D(actor);
        }
    }
    else {
        for (vtkActor2D* actor : getInfoActors2D()) {
            renderer->AddActor2D(actor);
        }
    }
    renderUpdateEvent();

}



void VtkWidget::popCenterMenu(QPoint pos){
    center_menu->popup(QCursor::pos());

}



void VtkWidget::viewOptionEvent() {


}


void VtkWidget::projectionViewEvent(bool checked) {
    camera->SetParallelProjection(checked);
    render_window->Render();

}


void VtkWidget::hideScreenInfo() {
    for (auto& actor : info_actors) {
        actor->SetVisibility(false);
    }

}


void VtkWidget::showScreenInfo() {
    for (auto& actor : info_actors) {
        actor->SetVisibility(true);
    }

}



void VtkWidget::removeRenderingIDinThis(int id) {
    std::vector<int>::iterator it = std::find(renderingid_inthis.begin(), renderingid_inthis.end(), id);
    renderingid_inthis.erase(it);

}

NAMESPACE_END

